﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Infrastructure;
using Infrastructure.DataTypes;
using Controllers;
using System.IO;

namespace RecommenderSystem
{
    public partial class MainForm : Form
    {
        
        Dispatcher m_cont;
        LoadUser m_loaduser;
        string m_active_user;
        string m_logdInUser;
        string m_logInUserID;
        string m_dataSource;
        Dictionary<string, Discrete> m_userScores;//save temporary scores of user
        public MainForm()
        {
            InitializeComponent(); 

        }
        public MainForm(Dispatcher cor, string user,string userID, string dataSource,bool ifnewUser)
        {
           
            InitializeComponent();
            m_cont = cor;
            m_userScores = new Dictionary<string, Discrete>();
            m_dataSource = dataSource;
            m_logInUserID = userID;
            LoadData(user,userID ,dataSource);
            dataGridView1.Columns[0].CellTemplate.ValueType = typeof(double);
            dataGridView1.Columns[0].ValueType = typeof(double);
            if (ifnewUser)
            {
                this.tabControl1.SelectedTab = this.tabControl1.TabPages["tabPageRate"];
            }
  
        }
       /// <summary>
       /// load needed data to all form containers
       /// </summary>
       /// <param name="user"></param>
       /// <param name="dataSource"></param>
        private void LoadData(string user,string userID, string dataSource)
        {

            List<string> toview = new List<string>(m_cont.PredictionAlgorithmList());
            this.checkedListBoxUser.DataSource = toview;
           
            toview = new List<string>(m_cont.StatisticalAnalysisAlgorithmList());
            this.checkedListBoxStTest.DataSource = toview;
            this.tabControl1.TabPages[0].Text = "Welcome " + user;
            m_active_user = m_logInUserID;
            labelUser.Text = m_active_user;
            m_logdInUser = user;
            if (!File.Exists(userID + dataSource + "Scores.txt"))
            {
                int index = 0;
                int sum = 2;
                if (dataSource == m_cont.dataSource()[0])
                {
                    UCLmovieDetails[] items = new UCLmovieDetails[50];

                    foreach (Item<Discrete> item in m_cont.TopNItems(50))
                    {
                        items[index] = new UCLmovieDetails(item);
                        items[index].ScoreSelection += new ScoreSelectEventHandler(MainForm_ScoreSelection);
                        items[index].Dock = DockStyle.Top;
                        
                        if (index == 0 || index==sum)
                        {
                            items[index].BackColor = Color.CornflowerBlue;
                            items[index].BorderStyle = BorderStyle.FixedSingle;
                            sum += 2;
                        }
                        index++;

                    }
                    panelItems.Controls.AddRange(items);

                }
                
            }
            else
            {
                if (dataSource == m_cont.dataSource()[0])
                {
                    UCLmovieDetails[] items = new UCLmovieDetails[50];
                    int index = 0;
                    int sum = 2;
                    foreach (Item<Discrete> item in m_cont.ItemsNotVotedByUser(m_logInUserID))
                    {
                        if (index==50)
                        {
                            break;
                        }
                        items[index] = new UCLmovieDetails(item);
                        items[index].ScoreSelection += new ScoreSelectEventHandler(MainForm_ScoreSelection);
                        items[index].Dock = DockStyle.Top;
                        if (index == 0 || index == sum)
                        {
                            items[index].BackColor = Color.CornflowerBlue;
                            items[index].BorderStyle = BorderStyle.FixedSingle;
                            sum += 2;
                        }
                        
                        index++;

                    }
                    panelItems.Controls.AddRange(items);

                }

            }
            foreach (KeyValuePair<string, string> item in m_cont.GetAllItems())
            {
                DataGridViewRow temp = new DataGridViewRow();
                temp.CreateCells(dataGridView1);
                string avg = Math.Round(m_cont.GetItem(item.Key).StatisticsAttributes.AverageRating, MidpointRounding.AwayFromZero).ToString();

                string ifscores = m_cont.GetUserVoteHistory(m_active_user).ContainsKey(m_cont.GetItem(item.Key)).ToString();
                string gn = " ";
                foreach (KeyValuePair<string, string> data in m_cont.GetItem(item.Key).Data_Attributes)
                {
                    switch (data.Key)
                    {
                        case "title":
                            break;
                        case "video_release_date":
                            break;
                        case "IMDb_URL":
                            break;
                        default:
                            if (gn == " ")
                            {
                                gn = gn + data.Value.ToString();
                            }
                            else
                            {
                                gn = gn + ", " + data.Value.ToString();
                            }
                            break;
                    }
                }
                temp.Cells[0].Value = System.Convert.ToDouble(item.Key);
                temp.Cells[1].Value = item.Value;
                temp.Cells[2].Value = avg;
                temp.Cells[3].Value = m_cont.GetItem(item.Key).StatisticsAttributes.VoteCount;
                temp.Cells[4].Value = ifscores;
                temp.Cells[5].Value = gn;
                this.dataGridView1.Rows.Add(temp);

            }

            setPopularItems(4);
            setRecommendedItems(m_active_user, 8);
        }
/// <summary>
/// if user vouted to some item
/// </summary>
/// <param name="itemID"></param>
/// <param name="rating"></param>
        private void MainForm_ScoreSelection(string itemID, int rating)
        {
            Discrete rt = rating;
            if (m_userScores.ContainsKey(itemID))
            {
                m_userScores[itemID] = rt;
            }
            else
            {
                m_userScores.Add(itemID, rt);
            }

        }
/// <summary>
/// prediction buuton was clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
        private void buttonPredUser_Click(object sender, EventArgs e)
        {

            listBoxRes.Items.Clear();
            string alg;
            double ans;
            string result;
            try
            {


                for (int i = 0; i < checkedListBoxUser.CheckedItems.Count; i++)
                {
                    alg = checkedListBoxUser.CheckedItems[i].ToString();
                    ans = m_cont.ActivatePredictionAlg(m_active_user, dataGridView1.SelectedRows[0].Cells[0].Value.ToString(), alg);

                    if (double.IsNaN(ans))
                    {
                        result = "Score predicted by " + checkedListBoxUser.CheckedItems[i].ToString() + ": " + "User didn't voted";
                    }
                    else
                    {
                        if (ans == 0)
                        {
                            result = "Score predicted by " + checkedListBoxUser.CheckedItems[i].ToString() + ": " + "Algorithm not implemented";
                        }

                        else
                        {
                            result = "Score predicted by " + checkedListBoxUser.CheckedItems[i].ToString() + ": " + ans;
                        }
                    }
                    
                    listBoxRes.Items.Add(result);


                }
            }
            catch (Exception ex)
            {

               MessageBox.Show(ex.Message);

            }
            
        }

        /// <summary>
        /// if check all items checkbox is checked for user implementation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxAllUser_CheckedChanged(object sender, EventArgs e)
        {
            bool flag;
            if (checkBoxAllUser.Checked)
            {
                flag = true;
            }
            else
            {
                flag = false;
            }
            for (int i = 0; i < checkedListBoxUser.Items.Count; i++)
            {
                this.checkedListBoxUser.SetItemChecked(i, flag);
            }

             
        }

        private void buttonGetUser_Click(object sender, EventArgs e)
        {
            m_loaduser = new LoadUser(m_cont);
            m_loaduser.ButtonClicked += new ButtonSetEventHandler(userRetriever);
            m_loaduser.ShowDialog();
        }
      

        private void userRetriever(User<Discrete> e)//when set user button is pressed this event is invoking
        {
            m_active_user = e.UserID;
            labelUser.Text = m_active_user;
           
        }
        /// <summary>
        /// compare for sort of colmns in datagridview
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
        {
            try
            {
                if ((e.Column.Name == dataGridView1.Columns[0].Name || e.Column.Name == dataGridView1.Columns[2].Name) || (e.Column.Name == dataGridView1.Columns[3].Name))
                {
                    e.SortResult = System.Convert.ToDouble(e.CellValue1).CompareTo(System.Convert.ToDouble(e.CellValue2));
                }
                else
                {
                    e.SortResult = System.String.Compare(e.CellValue1.ToString(), e.CellValue2.ToString());
                    

                }

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// save scores in data set
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSaveScores_Click(object sender, EventArgs e)
        {
            m_cont.WriteScoresToFile(m_logInUserID, m_dataSource, m_userScores);

            foreach (KeyValuePair<string,Discrete> item in m_userScores)
            {
                m_cont.AddNewScoreToDataSet(m_active_user, item.Key, item.Value);
                
            }
            LoadData(m_logdInUser, m_logInUserID, m_dataSource);
           // MessageBox.Show("Scores were saved ");
            MyMessageBox msgBox = new MyMessageBox("Scores were saved", "Saved");
            msgBox.ShowDialog();
        }

        private void buttonRunTest_Click(object sender, EventArgs e)
        {
            try
            {


                int cUsers = 0;
                if (int.TryParse(textBoxTestN.Text, out cUsers))
                {
                    if (this.checkedListBoxStAlg.CheckedItems.Count > 0 && checkedListBoxStTest.CheckedItems.Count > 0)
                    {

                        string alg = this.checkedListBoxStAlg.CheckedItems[0].ToString();
                        string test = this.checkedListBoxStTest.CheckedItems[0].ToString();
                        string testT = test.Trim();
                        List<string> lAlgorithms = new List<string>();
                        foreach (object i in checkedListBoxStAlg.CheckedItems)
                        {
                            alg = i.ToString().Trim();
                            lAlgorithms.Add(alg);
                        }
                        ComputationProgress progress = new ComputationProgress(m_cont);
                        Dictionary<string, object> dParameters = new Dictionary<string, object>();
                        dParameters["cUsers"] = cUsers;
                        dParameters["Test"] = testT;
                        dParameters["Algorithms"] = lAlgorithms;

                        progress.RunWorkerAsync("RMSE", dParameters);
                        progress.ShowDialog();
                        Dictionary<string, double> dScores = (Dictionary<string, double>)progress.ComputationResult;
                        //Dictionary<string, double> dScores = m_cont.RunStatisticalAnalysisBuiltIn(cUsers, testT, lAlgorithms);
                        foreach (KeyValuePair<string, double> p in dScores)
                        {
                            string ans = test + " score for";
                            ans = ans + " " + p.Key + " algorithm: ";
                            if (double.IsNaN(p.Value))
                                ans += "Algorithm not implemented";
                            else
                                ans += p.Value;
                            listBoxTestResult.Items.Add(ans);
                        }
                        progress.Hide();
                    }
                    else
                    {
                        // MessageBox.Show("Please select test and algorithm for test");
                        MyMessageBox msgBox = new MyMessageBox("Please select test\n and algorithm for test", "Select");
                        msgBox.ShowDialog();
                    }
                }
                else
                {
                   // MessageBox.Show("Please enter an integer number as amount of users");
                    MyMessageBox msgBox = new MyMessageBox("Please enter the \n number of users", "Enter Users");
                    msgBox.ShowDialog();
                }
            }
            catch (Exception EX)
            {

                MessageBox.Show(EX.Message);
            }
        }

        private void checkedListBoxStTest_SelectedValueChanged(object sender, EventArgs e)
        {
            List<string> toview;
            this.checkedListBoxStAlg.Items.Clear();
            foreach (string alg in m_cont.PredictionAlgorithmList())
            {
                 this.checkedListBoxStAlg.Items.Add(alg, false);  
            }
            
            for (int i = 0; i < checkedListBoxStTest.Items.Count; i++)
            {
                if (checkedListBoxStTest.Items[i].ToString()==checkedListBoxStTest.SelectedItem.ToString())
                {
                    checkedListBoxStTest.SetItemChecked(i, true);
                }
                else
                {
                    checkedListBoxStTest.SetItemChecked(i, false);
                }
            }
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            listBoxTestResult.Items.Clear();
        }



        #region welcome layout
        /// <summary>
        /// sets the (central) recommended panel. 
        /// uses random prediction and highest prediction for recomendation
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="numberOfItems">length of the predictions list</param>
        public void setRecommendedItems(string userID, int numberOfItems)
        {
            var votes = m_cont.ItemsNotVotedByUser(userID);
            Dictionary<Item<Discrete>, double> predictions = new Dictionary<Item<Discrete>, double>();

            foreach (Item<Discrete> item in votes)
            {
                //creating predictions
                double prediction = m_cont.ActivatePredictionAlg(userID, item.ItemID, "Pearson");
                predictions.Add(item, prediction);
            }

            //sorting list by highest prediction.
            var sortedCounts = from entry in predictions orderby entry.Value descending select entry.Key;
            sortedCounts = sortedCounts.Take(numberOfItems+6);

            List<Item<Discrete>> bestList = sortedCounts.ToList();
                     

            int index = 0;
            tableLayoutPanelRecommended.Controls.Clear();

            for (int i = 0; i < tableLayoutPanelRecommended.RowCount && bestList.Count > index; i++)
                for (int j = 0; j < tableLayoutPanelRecommended.ColumnCount && bestList.Count > index; j++)
                {
                    //setting the items to the recommendation panel
                    tableLayoutPanelRecommended.Controls.Add(new UCLWelcomeItem(bestList[index]), j, i);
                    index++;

                }
        }


        /// <summary>
        /// setting top ten popular items to the "popular" panel
        /// </summary>
        /// <param name="numberOfItems">number of items to add to panel</param>
        public void setPopularItems(int numberOfItems)
        {
            var topTenItems = m_cont.TopNItems(numberOfItems);


            //setting the items to the top Ten panel
            foreach (Item<Discrete> item in topTenItems)
            {
                UCLWelcomeItem uclTMP = new UCLWelcomeItem(item);

                uclTMP.BackgroundImage = imageList1.Images[0];
                flowLayoutPanelPopular.Controls.Add(uclTMP);

            }

        }
        #endregion

     

    }

}
